package com.hserver.system.service;

import com.alibaba.fastjson.JSON;
import com.hserver.system.entity.*;
import com.hserver.system.mapper.TokenMapper;
import com.hserver.system.utils.RedisUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import top.hserver.core.ioc.annotation.Autowired;
import top.hserver.core.ioc.annotation.Bean;
import top.hserver.core.server.context.Webkit;

import java.util.Date;
import java.util.List;
import java.util.UUID;

@Bean
public class TokenService {

    @Autowired
    private UserService userService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private SqlSessionFactory sqlSessionFactory;
    @Autowired
    private RedisUtil redisUtil;

    public String getToken(String username) {
        ConfigEntity p = configService.getConfig();
        if ("sql".equals(p.getTokenLocation())) {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            TokenMapper tokenMapper = sqlSession.getMapper(TokenMapper.class);
            TokenEntity token = tokenMapper.getToken(username);
            sqlSession.close();
            if (token.getCreateTime() != null && token.getCreateTime().getTime() + p.getTokenExpire() * 1000 < new Date().getTime() && p.getTokenExpire() != -1) {
                throw new RuntimeException("token已过期");
            } else {
                return token.getToken();
            }
        } else {
            String token = redisUtil.get("user:token:" + username);
            if (token == null) {
                throw new RuntimeException("未找到token");
            }
            return token;
        }
    }

    public boolean hasToken(String username) {
        ConfigEntity p = configService.getConfig();
        if ("sql".equals(p.getTokenLocation())) {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            TokenMapper tokenMapper = sqlSession.getMapper(TokenMapper.class);
            TokenEntity token = tokenMapper.getToken(username);
            sqlSession.close();
            if (token != null && token.getCreateTime() != null && token.getCreateTime().getTime() + p.getTokenExpire() * 1000 > new Date().getTime() && p.getTokenExpire() != -1) {
                return true;
            } else {
                return false;
            }
        } else {
            String token = redisUtil.get("user:token:" + username);
            if (token == null) {
                return false;
            }
            return true;
        }
    }

    /**
     * 生成新的Token，存入数据库或者mysql
     *
     * @param userEntity
     * @return
     */
    public String newToken(UserEntity userEntity) {
        ConfigEntity p = configService.getConfig();
        String token = UUID.randomUUID().toString().replace("-", "");
        if ("sql".equals(p.getTokenLocation())) {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            TokenMapper tokenMapper = sqlSession.getMapper(TokenMapper.class);
            TokenEntity tokenEntity = new TokenEntity();
            tokenEntity.setCreateBy(userEntity.getUsername());
            tokenEntity.setCreateTime(new Date());
            tokenEntity.setToken(token);
            tokenMapper.deleteByUsername(userEntity.getUsername());
            tokenMapper.saveToken(tokenEntity);
            sqlSession.commit();
            sqlSession.close();
            return tokenEntity.getToken();
        } else {
            //如果是Redis那么将菜单列表页存入，这样效果会更好
            List<PermissionEntity> permissionEntities = userService.getUserPermission(userEntity.getUsername());
            TokenInfo tokenInfo = new TokenInfo(userEntity, permissionEntities);
            String tokenInfoStr = JSON.toJSON(tokenInfo).toString();
            System.out.println(tokenInfoStr);
            if (p.getTokenExpire() == -1) {
                redisUtil.set("user:info:" + token, tokenInfoStr);
                redisUtil.set("user:token:" + userEntity.getUsername(), token);
            } else {
                redisUtil.setex("user:info:" + token, p.getTokenExpire(), tokenInfoStr);
                redisUtil.setex("user:token:" + userEntity.getUsername(), p.getTokenExpire(), token);
            }
            return token;
        }
    }

    public boolean requiresPermissions(String tokenStr, Webkit webkit) {
        ConfigEntity p = configService.getConfig();
        if ("sql".equals(p.getTokenLocation())) {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            TokenMapper tokenMapper = sqlSession.getMapper(TokenMapper.class);
            TokenEntity token = tokenMapper.getByToken(tokenStr);
            sqlSession.close();
            List<PermissionEntity> permissionEntities = userService.getUserPermission(getUsernameByToken(tokenStr));
            if (token.getCreateTime() != null && token.getCreateTime().getTime() + p.getTokenExpire() * 1000 < new Date().getTime() && p.getTokenExpire() != -1) {
                return false;
            } else {
                for (PermissionEntity permissionEntity : permissionEntities) {
                    //是按钮权限，同时是uri符合标准，
                    if (permissionEntity.getRoute() != null && !permissionEntity.getRoute() && permissionEntity.getPath() != null && permissionEntity.getPath().equals(webkit.httpRequest.getUri())) {
                        return true;
                    } else {
                        List<PermissionEntity> children = permissionEntity.getChildren();
                        if (children != null) {
                            for (PermissionEntity child : children) {
                                if (child.getRoute() != null && !child.getRoute() && child.getPath() != null && child.getPath().equals(webkit.httpRequest.getUri())) {
                                    return true;
                                }
                            }
                        }
                    }
                }
                return false;
            }
        } else {
            String s = redisUtil.get("user:info:" + tokenStr);
            if (s == null) {
                return false;
            }
            TokenInfo tokenInfo = JSON.parseObject(s, TokenInfo.class);
            for (String path : tokenInfo.getPermissionEntities()) {
                //是按钮权限，同时是uri符合标准，
                if (path != null && path.equals(webkit.httpRequest.getUri())) {
                    return true;
                }
            }
            return false;
        }
    }

    public String getUsernameByToken(String st) {
        ConfigEntity p = configService.getConfig();
        if ("sql".equals(p.getTokenLocation())) {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            TokenMapper tokenMapper = sqlSession.getMapper(TokenMapper.class);
            TokenEntity token = tokenMapper.getByToken(st);
            sqlSession.close();
            if (token.getCreateTime() != null && token.getCreateTime().getTime() + p.getTokenExpire() * 1000 < new Date().getTime() && p.getTokenExpire() != -1) {
                return null;
            } else {
                return token.getCreateBy();
            }
        } else {

            String s = redisUtil.get("user:info:" + st);
            TokenInfo tokenInfo = JSON.parseObject(s, TokenInfo.class);
            if (tokenInfo.getUserEntity().getUsername() == null) {
                return null;
            }
            return tokenInfo.getUserEntity().getUsername();
        }
    }
}
